module Utils

using TOML

export read_ini
export atrange2atlist, p, h, i, u, sel_fun, get_path, get_file, get_input, finish_path, prev_local2abs, check_file
export finish_hint, error_hint, request_hint, title_hint, warning_hint

function atrange2atlist(atom_selection_str::AbstractString)
    try
        selection_range = Vector{Int32}()
        if atom_selection_str == ""
            return selection_range
        end
        atom_selection_str = replace(atom_selection_str, r",\s*" => ",")
        atom_selection_str = replace(atom_selection_str, r"\s*-\s*" => "-")
        atom_selection_str = replace(atom_selection_str, r"\s+" => ",")
        sub_selections = split(atom_selection_str, ',')
        for s in sub_selections
            if '-' in s
                l, u = split(s, '-')
                append!(selection_range, range(parse(Int32, l), parse(Int32, u)))
            else
                push!(selection_range, parse(Int32, s))
            end
        end
        return selection_range
    catch
        error_hint("Error parsing atom_selection_str. Check input.\n")
        exit(1)
    end
end

function read_ini(ini)
    return TOML.parsefile(ini)
end

# color: rgbmycw
fc_table = Dict(["k" => ";30", "r" => ";31", "g" => ";32", "b" => ";34", "m" => ";35", "y" => ";33", "c" => ";36", "w" => ";37", "" => ""])
bg_table = Dict(["k" => ";40", "r" => ";41", "g" => ";42", "b" => ";44", "m" => ";45", "y" => ";43", "c" => ";46", "w" => ";47", "" => ""])

color_text(s::String, style::String, fc::String, bg::String) = "\033[$(style)$(fc_table[fc])$(bg_table[bg])m$(s)\033[0m"
p(s::String; fc="", bg="") = color_text(s, "0", fc, bg)
h(s::String; fc="", bg="") = color_text(s, "1", fc, bg)
i(s::String; fc="", bg="") = color_text(s, "2", fc, bg)
u(s::String; fc="", bg="") = color_text(s, "4", fc, bg)

# 获取功能选项, 转化为特定数据类型
function sel_fun(tp::DataType=String)
    while true
        para = strip(readline())
        try
            if tp <: Integer
                para = parse(tp, para)
            end
            return para
        catch
            error_hint("ERROR: Invalid input, try again.\n")
            continue
        end
    end
end

# 获取输出路径, 提示覆盖
function get_path(init_path::String, add_new=true, ext="")
    while true
        out_path = joinpath(dirname(init_path), "$(add_new ? "new_" : "")$(isempty(ext) ? basename(init_path) : splitext(basename(init_path))[1] * ".$ext")")
        request_hint("\nPlease input the output path and name of new file")
        println(", e.g., E:/Data/$(basename(out_path))")
        println("If left blank, the output path will be $out_path")
        out_path = get_input(out_path)
        if isfile(out_path)
            warning_hint("Warning: $(basename(out_path)) already exists, overwrite? [Y/n] ")
            if get_input("y") == "y"
                return out_path
            else
                continue
            end
        else
            return out_path
        end
    end
end

# 获取文件
function get_file(default::AbstractString, ext=""; infilename="")
    while true
        name = get_input(default)
        name = prev_local2abs(name, infilename)
        name = isempty(ext) ? name : name * ".$ext"
        if check_file(name)
            return name
        end
    end
end

# 转化"?"
function prev_local2abs(name, ref_file)
    if startswith(name, "?")
        name = joinpath(dirname(ref_file), name[2:end])
    end
    return name
end

# 确认文件存在
function check_file(filename)
    if !isfile(filename)
        error_hint("Error: $filename not exist.\n")
        return false
    else
        return true
    end
end

# 获取特定数据类型的输入
function get_input(default, tp::DataType=String)
    while true
        input = strip(readline())
        if !isempty(input)
            try
                if tp <: Number
                    return parse(tp, input)
                end
            catch
                error_hint("ERROR: input ($input) not $tp, try again.\n")
                continue
            end
            return input
        end
        return default
    end
end

# 输出结束语
function finish_path(out_path)
    finish_hint("Finished writing file to $out_path.\n")
end

function request_hint(info::String)
    print(h(info, fc="b"))
end

function finish_hint(info::String)
    print(h(info, fc="g"))
end

function title_hint(info::String)
    print(h(info, fc="c"))
end

function error_hint(info::String)
    print(h(info, fc="r"))
end

function warning_hint(info::String)
    print(h(info, fc="y"))
end

# 待优化
function get_mdparam(mdp_file::String, para::String)
    reg = Regex("\\s*$(para)\\s*=\\s*(.+)\\s*")
    return match(reg, filter(x -> occursin(reg, x), readlines(mdp_file))[1]).captures[1]
end

end # module
